//
// Created by user on 20-3-20.
//

#ifndef _TASK_H_
#define _TASK_H_

#include "../GeneralLibrary/Lib.h"
#include "../ExceptionManagement/Gate.h"
#include "../SystemServiceManagement/SystemService.h"
#include "../MemoryManagement/Memory.h"
#include "Cpu.h"
#include "Ptrace.h"

/*===========================  宏变量定义区  ===========================*/

#define KERNEL_CS    (0x08)
// 内核代码段
#define    KERNEL_DS    (0x10)

#define CLONE_FS        (1 << 0)
#define CLONE_FILES        (1 << 1)
#define CLONE_SIGNAL    (1 << 2)

// 栈大小32K
#define STACK_SIZE 32768

#define     TASK_RUNNING           (1 << 0)
#define     TASK_INTERRUPTIBLE     (1 << 1)
#define     TASK_UNINTERRUPTIBLE   (1 << 2)
#define     TASK_ZOMBIE            (1 << 3)
#define     TASK_STOPPED           (1 << 4)

// 进程结构体的标志位
#define PF_KTHREAD      (1 << 0)
#define NEED_SCHEDULE	(1UL << 1)


// 当前进程 TASK 的基地址
#define current getCurrent()

#define GET_CURRENT			\
	"movq	%rsp,	%rbx	\n\t"	\
	"andq	$-32768,%rbx	\n\t"

/*===========================  宏函数定义区  ===========================*/

// 用来初始化进程的信息
#define INIT_TASK(tsk)	\
{			\
	.state = TASK_UNINTERRUPTIBLE,		\
	.flags = PF_KTHREAD,		\
    .preemptCount = 0,		\
	.signal = 0,		\
    .cpuID = 0,		\
	.memorySpaceDistribution = &memorySpaceDistribution,			\
	.thread = &initThread,		\
	.addressLimit = 0xffff800000000000,	\
	.pid = 0,			\
	.priority = 2,		\
	.vrunTime = 0		\
}

// 用来初始化任务状态段的
#define INIT_TSS \
{    .reserved0 = 0,     \
    .rsp0 = (unsigned long)(initTaskUnion.stack + STACK_SIZE / sizeof(unsigned long)),    \
    .rsp1 = (unsigned long)(initTaskUnion.stack + STACK_SIZE / sizeof(unsigned long)),    \
    .rsp2 = (unsigned long)(initTaskUnion.stack + STACK_SIZE / sizeof(unsigned long)),    \
    .reserved1 = 0,     \
    .ist1 = 0xffff800000007c00,    \
    .ist2 = 0xffff800000007c00,    \
    .ist3 = 0xffff800000007c00,    \
    .ist4 = 0xffff800000007c00,    \
    .ist5 = 0xffff800000007c00,    \
    .ist6 = 0xffff800000007c00,    \
    .ist7 = 0xffff800000007c00,    \
    .reserved2 = 0,    \
    .reserved3 = 0,    \
    .ioMapBaseAddress = 0    \
}

// 用来保存一些信息
#define switchTo(prev, next)            \
do{							\
	__asm__ __volatile__ (	"pushq	%%rbp	\n\t"	\
                            "pushq	%%rax	\n\t"	\
                            "movq	%%rsp,	%0	\n\t"	\
                            "movq	%2,	%%rsp	\n\t"	\
                            "leaq	1f(%%rip),	%%rax	\n\t"	\
                            "movq	%%rax,	%1	\n\t"	\
                            "pushq	%3		\n\t"	\
                            "jmp	__switch_to	\n\t"	\
                            "1:	\n\t"	\
                            "popq	%%rax	\n\t"	\
                            "popq	%%rbp	\n\t"	\
                            :"=m"(prev->thread->rsp),"=m"(prev->thread->rip)		\
                            :"m"(next->thread->rsp),"m"(next->thread->rip),"D"(prev),"S"(next)	\
                            :"memory"		\
                            );			\
}while(0)

/*===========================  结构体重命名区  ===========================*/

typedef struct MemorySpaceDistributionStruct MemorySpaceDistribution;
typedef struct ThreadStruct Thread;
typedef struct TaskStruct Task;
typedef struct TssStruct Tss;

/*===========================  外部变量声明区  ===========================*/

extern Thread initThread;
extern MemorySpaceDistribution memorySpaceDistribution;
extern union TaskUnion initTaskUnion;

//extern Task * initTask[NR_CPUS];

extern char _text;
extern char _etext;
extern char _data;
extern char _edata;
extern char _rodata;
extern char _erodata;
extern char _bss;
extern char _ebss;
extern char _end;

extern unsigned long kallsyms_addresses[] __attribute__((weak));
extern long kallsyms_syms_num __attribute__((weak));
extern long kallsyms_index[] __attribute__((weak));
extern char* kallsyms_names __attribute__((weak));

// 这个在 head.S 文件中定义的，它是第一个进程的内核栈基地址
extern unsigned long _stack_start;

/*===========================  结构体定义区  ===========================*/

// 页目录
typedef struct {
    unsigned long pml4t;
} pml4t_t;

/**
 * 内存空间分布结构体
 */
struct MemorySpaceDistributionStruct {

    pml4t_t *pgd;                    // CR3存放的地址

    unsigned long startCode;        // 代码段开始地址
    unsigned long endCode;          // 代码段结束地址

    unsigned long startData;        // 数据段开始地址
    unsigned long endData;          // 数据段结束地址

    unsigned long startRodata;      // 只读数据段开始地址
    unsigned long endRodata;        // 只读数据段结束地址

    unsigned long startBrk;         // 动态内存分配开始地址
    unsigned long endBrk;           // 动态内存分配结束地址

    unsigned long startStack;       // 应用层栈基地址

};

/**
 * 线程结构体
 * 用来保存线程的信息
 */
struct ThreadStruct {

    unsigned long rsp0;             // 内核层栈基地址

    unsigned long rip;              // 内核层代码指针
    unsigned long rsp;              // 内核层当前栈指针

    unsigned long fs;               // FS段寄存器
    unsigned long gs;               // GS段寄存器

    unsigned long cr2;              // CR2控制寄存器
    unsigned long trapNumber;       // 异常号
    unsigned long errorCode;        // 错误代码

    List list;                      // 双向链表

};

/**
 * 任务结构体
 * 也就是PCB（进程控制块）
 */
struct TaskStruct {

    volatile long state;                                // 进程的状态
    unsigned long flags;                                // 进程的标志
    long preemptCount;                                  // 进程占用的自旋锁数量
    long signal;                                        // 进程持有的信号
    long cpuID;		                                    // CPU ID

    MemorySpaceDistribution *memorySpaceDistribution;  // 内存空间分布结构体
    Thread *thread;                                    // 进程切换是保留的状态信息

    List list;                                          // 双向链表，用于连接各个进程控制结构体

    unsigned long addressLimit;                         // 进程地址空间范围
    /*0x0000,0000,0000,0000 - 0x0000,7fff,ffff,ffff user*/
    /*0xffff,8000,0000,0000 - 0xffff,ffff,ffff,ffff kernel*/

    long pid;                                           // 进程的ID号

    long priority;                                      // 进程的优先级

    long vrunTime;                                       // 进程可用时间片
};

// 定义内核层栈空间结构
union TaskUnion {

    Task task;                                                  // 1KB 进程信息使用
    unsigned long stack[STACK_SIZE / sizeof(unsigned long)];    // 31KB 内核栈使用

}__attribute__((aligned (8)));    // 8字节对齐

/**
 * 任务状态段结构体
 */
struct TssStruct {

    unsigned int reserved0;            // 保留位
    unsigned long rsp0;                 // 栈指针 0
    unsigned long rsp1;
    unsigned long rsp2;
    unsigned long reserved1;
    unsigned long ist1;
    unsigned long ist2;
    unsigned long ist3;
    unsigned long ist4;
    unsigned long ist5;
    unsigned long ist6;
    unsigned long ist7;
    unsigned long reserved2;
    unsigned short reserved3;
    unsigned short ioMapBaseAddress;    // IO 许可位图

}__attribute__((packed));

/*===========================  函数声明区  ===========================*/

// 获取当前进程 TASK 结构体的基地址
Task *getCurrent();

/**
 * 切换进程
 * @param prev 上一个进程
 * @param next 下一个进程
 */
void __switch_to(Task *prev, Task *next);

/**
 * 进程的入口函数
 * @param arg 参数
 * @return
 */
unsigned long init(unsigned long arg);

/**
 * 创建进程函数
 * @param function 创建完进程后要执行的函数
 * @param arg 要传给上面要执行的函数的参数
 * @param flags 进程的标志
 * @return
 */
unsigned long kernelThread(unsigned long (*function)(unsigned long), unsigned long arg, unsigned long flags);

void taskInit();

/**
 * 这个是在switch.S里面定义的
 * 系统调用后返回用的函数
 */
extern void returnSystemCall();

/**
 * 具体的系统调用
 * @param regs 系统调用时应用层寄存器的值
 * @return
 */
unsigned long systemCallFunction(PerformSite *regs);

/**
 * 创建进程函数
 */
extern void kernelThreadFunc(void);

extern void systemCall();

unsigned long doFork(PerformSite *regs, unsigned long cloneFlags, unsigned long stackStart, unsigned long stackSize);

/**
 * 进程退出时执行的函数
 * @param code 退出代码
 * @return
 */
unsigned long doExit(unsigned long code);

#endif //_TASK_H_
